package me.flyray.bsin.server.controller;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
import me.chanjar.weixin.cp.message.WxCpMessageRouter;
import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.flyray.bsin.cache.BsinCacheProvider;
import me.flyray.bsin.enums.WxPlatformType;
import me.flyray.bsin.server.biz.MsgHandlerBiz;
import me.flyray.bsin.server.biz.SubscribeHandlerBiz;
import me.flyray.bsin.server.domain.TenantWxPlatform;
import me.flyray.bsin.server.mapper.AiTenantWxPlatformMapper;
import me.flyray.bsin.thirdauth.wx.utils.BsinWxCpServiceUtil;
import me.flyray.bsin.thirdauth.wx.utils.BsinWxMpServiceUtil;

import me.flyray.bsin.thirdauth.wx.utils.WxCpProperties;
import me.flyray.bsin.thirdauth.wx.utils.WxMpProperties;
import me.flyray.bsin.utils.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import static me.chanjar.weixin.common.api.WxConsts.EventType.SUBSCRIBE;
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.*;

/**
 * @author <a href="https://github.com/binarywang">Binary Wang</a>
 */
@Slf4j
@RestController
//@RequestMapping("/wx/portal/{appid}")
//@RequestMapping("/")
public class WxPortalController {

    @Autowired
    private MsgHandlerBiz msgHandlerBiz;
    @Autowired
    private SubscribeHandlerBiz subscribeHandlerBiz;
    @Autowired
    BsinWxMpServiceUtil bsinWxMpServiceUtil;
    @Autowired
    BsinWxCpServiceUtil bsinWxCpServiceUtil;
    @Autowired
    private BsinCacheProvider bsinCacheProvider;
    @Autowired
    private AiTenantWxPlatformMapper tenantWxPlatformMapper;

    @Value("${bsin.ai.aesKey}")
    private String aesKey;


    @GetMapping(value = "/{appid}", produces = "text/plain;charset=utf-8")
    public String authGet(@PathVariable String appid,
                          @RequestParam(name = "signature", required = false) String signature,
                          @RequestParam(name = "timestamp", required = false) String timestamp,
                          @RequestParam(name = "nonce", required = false) String nonce,
                          @RequestParam(name = "echostr", required = false) String echostr) {

        // 执行AI编排


        log.info("\n接收到来自微信服务器的认证消息：[{}, {}, {}, {}]", signature,
                timestamp, nonce, echostr);
        if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
            throw new IllegalArgumentException("请求参数非法，请核实!");
        }

        TenantWxPlatform tenantWxPlatform = tenantWxPlatformMapper.selectByAppId(appid);

        if (StringUtils.equals(tenantWxPlatform.getWxType(), WxPlatformType.MP.getType())) {
            log.debug("微信公众号请求验证");
            WxMpProperties.MpConfig config = new WxMpProperties.MpConfig();
            config.setAesKey(tenantWxPlatform.getAesKey());
            config.setAppId(appid);
            SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, aesKey.getBytes());
            config.setSecret(aes.decryptStr(tenantWxPlatform.getAppSecret(), CharsetUtil.CHARSET_UTF_8));
            config.setToken(tenantWxPlatform.getToken());

            WxMpService wxService = bsinWxMpServiceUtil.getWxMpService(config,null);

            if (!wxService.switchover(appid)) {
                throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置，请核实！", appid));
            }
            //TODO: 校验失败
            if (wxService.checkSignature(timestamp, nonce, signature)) {
                return echostr;
            }
        } else if (tenantWxPlatform.getWxType() == WxPlatformType.CP.getType()) {
            log.debug("微信企业号|企业微信请求验证");

        }
        return "非法请求";
    }


    @PostMapping(value = "/{appid}", produces = "application/xml; charset=UTF-8")
    public String post(@PathVariable String appid,
                       @RequestBody String requestBody,
                       @RequestParam("signature") String signature,
                       @RequestParam("timestamp") String timestamp,
                       @RequestParam("nonce") String nonce,
                       @RequestParam("openid") String openid,
                       @RequestParam(name = "encrypt_type", required = false) String encType,
                       @RequestParam(name = "msg_signature", required = false) String msgSignature) {
        log.debug("\n接收微信请求：[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}],"
                        + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
                openid, signature, encType, msgSignature, timestamp, nonce, requestBody);

        String out = null;
        WxMpXmlOutMessage outMessage = null;
        TenantWxPlatform tenantWxPlatform = tenantWxPlatformMapper.selectByAppId(appid);
        if (tenantWxPlatform == null) {
            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置，请核实！", appid));
        }
        WxMpProperties.MpConfig config = new WxMpProperties.MpConfig();
        config.setAesKey(tenantWxPlatform.getAesKey());
        config.setAppId(appid);
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, aesKey.getBytes());
        config.setSecret(aes.decryptStr(tenantWxPlatform.getAppSecret(), CharsetUtil.CHARSET_UTF_8));
        config.setToken(tenantWxPlatform.getToken());

        WxMpService wxService = bsinWxMpServiceUtil.getWxMpService(config,null);
        if (!wxService.switchover(appid)) {
//            new TextBuilder().build(String.format("未找到对应appid=[%s]的配置，请核实！", appid), null, wxService);
            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置，请核实！", appid));
        }

        if (!wxService.checkSignature(timestamp, nonce, signature)) {
//            return String.format("非法请求，可能属于伪造的请求！");
            throw new IllegalArgumentException("非法请求，可能属于伪造的请求！");
        }

        if (encType == null) {
            // 明文传输的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
            inMessage.getFromUser();
            bsinCacheProvider.set(inMessage.getFromUser(), appid);
            outMessage = this.route(inMessage, wxService);
            if (outMessage == null) {
                return "";
            }

            out = outMessage.toXml();
        } else if ("aes".equalsIgnoreCase(encType)) {
            // aes加密的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(),
                    timestamp, nonce, msgSignature);
            log.debug("\n消息解密后内容为：\n{} ", inMessage.toString());
            bsinCacheProvider.set(inMessage.getFromUser(), appid);
            outMessage = this.route(inMessage, wxService);
            if (outMessage == null) {
                return "";
            }

            out = outMessage.toEncryptedXml(wxService.getWxMpConfigStorage());
        }
//        log.debug("\n组装回复信息：{}", out);
        return out;
    }

    private WxMpXmlOutMessage route(WxMpXmlMessage message, WxMpService wxMpService) {

        final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);

        // 默认
        newRouter.rule().async(false).msgType(TEXT).handler(msgHandlerBiz).end();
        // 关注事件
        newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(subscribeHandlerBiz).end();
//        // 取消关注事件
//        newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(subscribeHandlerBiz).end();

        try {
            return newRouter.route(message);
        } catch (Exception e) {
            log.error("路由消息时出现异常！", e);
        }

        return null;
    }
//    @Bean
//    public WxMpMessageRouter messageRouter(WxMpService wxMpService) {
//        final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);
//        // 记录所有事件的日志 （异步执行）
//        newRouter.rule().handler(this.logHandler).next();
//        // 接收客服会话管理事件
//        newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION)
//                .handler(this.kfSessionHandler).end();
//        newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION)
//                .handler(this.kfSessionHandler).end();
//        newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION)
//                .handler(this.kfSessionHandler).end();
//        // 门店审核事件
//        newRouter.rule().async(false).msgType(EVENT).event(POI_CHECK_NOTIFY).handler(this.storeCheckNotifyHandler).end();
//        // 自定义菜单事件
//        newRouter.rule().async(false).msgType(EVENT).event(EventType.CLICK).handler(this.menuHandler).end();
//        // 点击菜单连接事件
//        newRouter.rule().async(false).msgType(EVENT).event(EventType.VIEW).handler(this.nullHandler).end();
//        // 关注事件
//        newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end();
//        // 取消关注事件
//        newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end();
//        // 上报地理位置事件
//        newRouter.rule().async(false).msgType(EVENT).event(EventType.LOCATION).handler(this.locationHandler).end();
//        // 接收地理位置消息
//        newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end();
//        // 扫码事件
//        newRouter.rule().async(false).msgType(EVENT).event(EventType.SCAN).handler(this.scanHandler).end();
//        // 默认
//        newRouter.rule().async(false).handler(this.msgHandler).end();
//        return newRouter;
//    }


    @GetMapping(value = "/{corpId}/{agentId}", produces = "text/plain;charset=utf-8")
    public String authGet(@PathVariable String corpId,
                          @PathVariable Integer agentId,
                          @RequestParam(name = "msg_signature", required = false) String signature,
                          @RequestParam(name = "timestamp", required = false) String timestamp,
                          @RequestParam(name = "nonce", required = false) String nonce,
                          @RequestParam(name = "echostr", required = false) String echostr) {
        log.info("\n接收到来自微信服务器的认证消息：[{}, {}, {}, {}]", signature,
                timestamp, nonce, echostr);

        if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
            throw new IllegalArgumentException("请求参数非法，请核实!");
        }
        TenantWxPlatform tenantWxPlatform = tenantWxPlatformMapper.selectByCorpAgentId(corpId, agentId.toString());
        if (StringUtils.equals(tenantWxPlatform.getWxType(), WxPlatformType.CP.getType())) {
            log.debug("微信企业号|企业微信请求验证");
            WxCpProperties.CpConfig config = new WxCpProperties.CpConfig();
            config.setAesKey(tenantWxPlatform.getAesKey());
            config.setCorpId(corpId);
            config.setAgentId(agentId);
            SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, aesKey.getBytes());
            config.setSecret(aes.decryptStr(tenantWxPlatform.getAppSecret(), CharsetUtil.CHARSET_UTF_8));
            config.setToken(tenantWxPlatform.getToken());
            WxCpService wxCpService = bsinWxCpServiceUtil.getWxCpService(config);
            if (wxCpService == null) {
                throw new IllegalArgumentException(String.format("未找到对应agentId=[%d]的配置，请核实！", agentId));
            }
            if (wxCpService.checkSignature(signature, timestamp, nonce, echostr)) {
                return new WxCpCryptUtil(wxCpService.getWxCpConfigStorage()).decrypt(echostr);
            }
        }
        return "非法请求";
    }


    @PostMapping(produces = "application/xml; charset=UTF-8")
    public String post(@PathVariable String corpId,
                       @PathVariable Integer agentId,
                       @RequestBody String requestBody,
                       @RequestParam("msg_signature") String signature,
                       @RequestParam("timestamp") String timestamp,
                       @RequestParam("nonce") String nonce) {
        log.info("\n接收微信请求：[signature=[{}], timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
                signature, timestamp, nonce, requestBody);

        TenantWxPlatform tenantWxPlatform = tenantWxPlatformMapper.selectByAppId(corpId + agentId.toString());
        WxCpProperties.CpConfig config = new WxCpProperties.CpConfig();
        config.setAesKey(tenantWxPlatform.getAesKey());
        config.setCorpId(corpId);
        config.setAgentId(agentId);

        final WxCpService wxCpService = bsinWxCpServiceUtil.getWxCpService(config);
        if (wxCpService == null) {
            throw new IllegalArgumentException(String.format("未找到对应agentId=[%d]的配置，请核实！", agentId));
        }

        WxCpXmlMessage inMessage = WxCpXmlMessage.fromEncryptedXml(requestBody, wxCpService.getWxCpConfigStorage(),
                timestamp, nonce, signature);
        log.debug("\n消息解密后内容为：\n{} ", JsonUtils.toJson(inMessage));
//        WxCpXmlOutMessage outMessage = this.route(corpId, agentId, inMessage);
//        if (outMessage == null) {
//            return "";
//        }

//        String out = outMessage.toEncryptedXml(wxCpService.getWxCpConfigStorage());
//        log.debug("\n组装回复信息：{}", out);
//        return out;
        return null;
    }

//    private WxCpXmlOutMessage route(String corpId, Integer agentId, WxCpXmlMessage message) {
//
//        final WxCpMessageRouter newRouter = new WxCpMessageRouter(wxMpService);
//        try {
//            return WxCpConfiguration.getRouters().get(corpId + agentId).route(message);
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//        }
//
//        return null;
//    }

}
